import { SM } from '/@/utils/sm';
import { Session } from '/@/utils/storage';

/**
 * 参数类型判断
 * @param obj
 * @returns string
 */
function dataTypeof(obj?: any) {
	let type = Object.prototype.toString.call(obj);
	return type.substring(8, type.length - 1);
}

/**
 * 参数转成字符串，并按升序排序
 * @param obj
 * @returns string
 */
function dataToStringAndSort(obj: any) {
	if ('Array' === dataTypeof(obj)) {
		const arr = obj.concat().sort();
		if(arr && arr.length > 0){
			for (let i = 0; i < obj.length; i++) {
				arr[i] = dataToStringAndSort(obj[i]);
			}
			return arr;
		}
		return '';
	} else if ('Object' === dataTypeof(obj)) {
		const keys = Object.keys(obj)?.sort();
		if(keys && keys.length > 0){
			const data = {} as any;
			for (let i = 0; i < keys.length; i++) {
				data[keys[i]] = dataToStringAndSort(obj[keys[i]]);
			}
			return data;
		}
		return '';
	} else if ('Number' === dataTypeof(obj) || 'Boolean' === dataTypeof(obj) || 'String' === dataTypeof(obj)) {
		const res = obj !== null ? obj.toString() : '';
		return res;
	} else if ('Undefined' === dataTypeof(obj) || 'Null' === dataTypeof(obj)) {
		return '';
	}
	return '';
}

/**
 * 参数签名序列化
 * @param obj
 */
function dataSignSerialize(obj: any) {
	let str = '';
	const data = dataToStringAndSort(obj);
	if ('Array' === dataTypeof(data)) {
		if(data.length > 0){
			//如果是数组则给定一个key=array
			str = `&array=${JSON.stringify(data.sort())}`;
		}
	} else if ('Object' === dataTypeof(data)) {
		const keys = Object.keys(data)?.sort();
		for (let i = 0; i < keys.length; i++) {
			let key = keys[i];
			const value = 'Object' === dataTypeof(data[key]) || 'Array' === dataTypeof(data[key]) ? JSON.stringify(data[key]) : data[key];
			if(value !== null && value !== '' && value != '[]' && value !== '{}'){
				str += `&${key}=${value}`;
			}
		}
	}
	return str;
}

export const Sign = {
	/**
	 * 参数签名
	 * @param options={url: string, params: object, data: object}
	 * @returns string
	 */
	signature: (options: any) => {
		const url = dataSignSerialize({'url': options?.url || ''});
		const params = dataSignSerialize(options?.params || '');
		const data = dataSignSerialize(options?.data || '');
		const random = Math.random().toString(36).substring(2);
		const secret = dataSignSerialize({'secret': random});
		//客户端时间加上时间差
		const nowtime = new Date().getTime() + Session.get('timediffer');
		const timestamp = dataSignSerialize({'timestamp': nowtime});
		// 生成签名字符串
		const signstr = url.substring(1) + params + data + secret + timestamp;
		
		return {
			signature: SM.sm3Encrypt(signstr),
			secret: random,
			timestamp: nowtime,
		}
	}
}